/*
Coder: Dzlua
Email: 505544956@qq.com
Time : 2017/05/18
*/
#include "sock.h"
#include "task.h"

#pragma comment(lib,"ws2_32.lib")

Service::Service() {}

Service::~Service() {
    closesocket(m_sock);
	WSACleanup();
}

bool Service::Init(unsigned short port) {
    WORD wVersion;
	WSADATA wsaData;
	wVersion = MAKEWORD(1, 1);
	int err = WSAStartup(wVersion, &wsaData);
	if (0 != err)
		return false;

	if (wsaData.wVersion != wVersion) {
		WSACleanup();
		return false;
	}

    m_sock = socket(AF_INET, SOCK_DGRAM, 0);
	SOCKADDR_IN addrSrv;
	addrSrv.sin_addr.S_un.S_addr = INADDR_ANY;
	addrSrv.sin_family = AF_INET;
	addrSrv.sin_port = htons(port);

    err = bind(m_sock, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    if (0 != err)
		return false;
    return true;
}

void Service::Send(SOCKADDR_IN &addrClient, int addr_len, const std::string& data) {
	sendto(m_sock, data.data(), data.length(), 0, (SOCKADDR*)&addrClient, addr_len);
}

void Service::Listen() {
    SOCKADDR_IN addrClient;
	char buf[256];
	int addr_len = sizeof(SOCKADDR);
	int len;

    while (true) {
		len = recvfrom(m_sock, buf, sizeof(buf), 0, (SOCKADDR*)&addrClient, &addr_len);
        if (len == -1) {
            Send(addrClient, addr_len, "receive failed.");
            continue;
        }

        std::string str(buf, len);
        
        CmdTask task;
        if (!task.Deserialization(str)) {
            Send(addrClient, addr_len, "deserialization failed.");
            continue;
        }
        task.Run();
	}
}

//----------------------------------------//
Client::Client() {}

Client::~Client() {
    closesocket(m_sock);
	WSACleanup();
}

bool Client::Init(const std::string& ip, unsigned short port) {
    WORD wVersion;
	WSADATA wsaData;
	wVersion = MAKEWORD(1, 1);
	int err;
	err = WSAStartup(wVersion, &wsaData);
	if (0 != err)
		return false;

	if (wsaData.wVersion != wVersion) {
		WSACleanup();
		return false;
	}

    m_sock = socket(AF_INET, SOCK_DGRAM, 0);
	SOCKADDR_IN m_addr;
	m_addr.sin_addr.S_un.S_addr = inet_addr(ip.c_str());
	m_addr.sin_family = AF_INET;
	m_addr.sin_port = htons(port);

    return true;
}

void Client::Send(const std::string& data) {
    sendto(m_sock, data.data(), data.length(), 0, (SOCKADDR*)&m_addr, sizeof(SOCKADDR));
}

void Client::Send(CmdTask* task) {
    if (!task) return;
    std::string data = task->Serialization();
    if (data.empty()) return;
    Send(data);
}

std::string Client::Receive() {
    SOCKADDR_IN addr;
    char buf[256];
	int addr_len = sizeof(SOCKADDR);
	int len;
    len = recvfrom(m_sock, buf, sizeof(buf), 0, (SOCKADDR*)&addr, &addr_len);
    if (len == -1) return std::string();
    return std::move(std::string(buf, len));
}